/*=============================================================
* 	Copyright (C) 2024 USTC All rights reserved.
* 	
* 	filename : noc.cpp
* 	Author: Wei Jinsong
* 	Mail: vitus@mainl.ustc.edu.cn
* 	Date 2024-05-13
* 	Abstract 
* 		
*
=============================================================*/

#include "noc.h"
#include "utils.h"

using namespace sc_core;

BaseNoC::BaseNoC(sc_module_name name, uint32_t port_num, sc_clock& clock)
    : sc_module(name)
    , mExternalPortNum(port_num)
{
    txSpikePorts = new sc_port<SpikeInterface<>>*[port_num];
    rxSpikeFifo = new SpikeFifo<SpikePayload*>*[port_num];
    for (int i=0; i<port_num; i++) {
        sc_port<SpikeInterface<>>* port = new sc_port<SpikeInterface<>>;
        txSpikePorts[i] = port;
        rxSpikeFifo[i] = new SpikeFifo<SpikePayload*>(2048);
    }
    clk(clock);

    SC_THREAD(exec);
    sensitive << clk->posedge_event();
}

BaseNoC::~BaseNoC()
{
    delete [] txSpikePorts;
    delete [] rxSpikeFifo;
}

bool
BaseNoC::spike_transport_fw(SpikePayload &trans, sc_core::sc_time &delay)
{
    uint32_t srcid = trans.srcid;

    if (rxSpikeFifo[srcid]->nb_write(&trans)) {
        return true;
    }
    
    return false;
}

void 
BaseNoC::exec()
{
    SpikePayload* spike;
    while (true) {
        for (int i=0; i<mExternalPortNum; i++) {
            if (rxSpikeFifo[i]->num_available()>0) {

                SpikePayload* tmp = rxSpikeFifo[i]->front();

                uint32_t tgtid = tmp->tgtid;
                sc_time delay = SC_ZERO_TIME;
                if ((*(txSpikePorts[tgtid]))->spike_transport_fw(*tmp, delay)) {
                    rxSpikeFifo[i]->read(spike);
                }
            }
        }
        wait();
    }
}

